<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.14"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>LibQQt: DEBUGGING</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="logo.png"/></td>
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">LibQQt
   &#160;<span id="projectnumber">v3.1</span>
   </div>
   <div id="projectbrief">开源、跨平台Qt应用程序框架中间件</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.14 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">DEBUGGING </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>These are a couple of debugging notes that may be helpful for anyone developing Gumbo or trying to diagnose a tricky problem. They will probably not be necessary for normal clients of this library - Gumbo is relatively stable, and bugs are often rare and obscure. However, they're handy to have as a reference, and may also provide useful Google fodder to people searching for these tools.</p>
<p>Standard disclaimer: I use all of these techniques on my Ubuntu 14.04 computer with gcc 4.8.2, clang 3.4, and gtest 1.6.0, but make no warranty about them working on other systems. In particular, they're almost certain not to work on Windows.</p>
<h1>Debug output </h1>
<p>Gumbo has a compile-time switch to dump lots of debug output onto stdout. Compile with the GUMBO_DEBUG define enabled:</p>
<div class="fragment"><div class="line">$ make CFLAGS=&#39;-DGUMBO_DEBUG&#39;</div></div><!-- fragment --><p>Note that this spits <em>a lot</em> of debug information to the console and makes the program run significantly slower, so it's usually helpful to isolate only the specific HTML file or fragment that causes the bug. It lets us trace the operation of each of the tokenizer &amp; parser's state machines in depth, though.</p>
<h1>Unit tests </h1>
<p>As mentioned in the README, Gumbo relies on <a href="https://code.google.com/p/googletest/">googletest</a> for unit tests. Unzip the gtest ZIP distribution inside the Gumbo root and rename it 'gtest'. 'make check' runs the tests, as normal.</p>
<div class="fragment"><div class="line">$ make check</div><div class="line">$ cat test-suite.log</div></div><!-- fragment --><p>If you need to debug a core dump, you'll probably want to run the test binary directly:</p>
<div class="fragment"><div class="line">$ ulimit -c unlimited</div><div class="line">$ make check</div><div class="line">$ .libs/lt-gumbo_test</div><div class="line">$ gdb .libs/lt-gumbo_test core</div></div><!-- fragment --><p>The same goes for core dumps in other example binaries.</p>
<p>To run only a single unit test, pass the &ndash;gtest_filter='TestName' flag to the lt-gumbo_test binary.</p>
<h1>Assertions </h1>
<p>Gumbo relies pretty heavily on assertions. By default they're enabled at run-time: to turn them off, define NDEBUG:</p>
<div class="fragment"><div class="line">$ make CFLAGS=&#39;-DNDEBUG&#39;</div></div><!-- fragment --><h1>ASAN </h1>
<p>Google's <a href="https://code.google.com/p/address-sanitizer/">address-sanitizer</a> is a helpful tool that lets you find memory errors with relatively low overhead: enough that you can often run it in production. Enabling it for C/C++ binaries is pretty standard and described on the ASAN documentation pages. It requires Clang &gt;=3.1 or GCC &gt;= 4.8.</p>
<div class="fragment"><div class="line">$ make \</div><div class="line">    CFLAGS=&#39;-fsanitize=address -fno-omit-frame-pointer -fno-inline&#39; \</div><div class="line">    LDFLAGS=&#39;-fsanitize=address&#39;</div></div><!-- fragment --><p>ASAN can also be used when Gumbo is compiled as a shared library and linked into a scripting language via FFI, but this use-case is unsupported by the ASAN authors. To do it, use LD_PRELOAD to ensure the ASAN runtime support is included in the process:</p>
<div class="fragment"><div class="line">$ LD_PRELOAD=libasan.so.0 python -c &#39;import gumbo; gumbo.parse(problem_text)&#39;</div></div><!-- fragment --><p>Getting clean stack traces from this requires the use of the llvm-symbolizer binary, included with clang:</p>
<div class="fragment"><div class="line">$ export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.4</div><div class="line">$ export ASAN_OPTIONS=symbolize=1</div><div class="line">$ LD_PRELOAD=libasan.so.0 python -c \</div><div class="line">  &#39;import gumbo; gumbo.parse(problem_text)&#39; 2&gt;&amp;1 | head -100</div><div class="line">$ killall llvm-symbolizer-3.4</div><div class="line">$ killall llvm-symbolizer-3.4</div><div class="line">$ killall llvm-symbolizer-3.4</div></div><!-- fragment --><p>This use case is even less officially supported than using it with dynamic shared objects; on my machine, it led to a recursive ASAN error about a use-after-free in llvm-symbolizer, effectively fork-bombing the machine. Have the killalls ready, and avoid letting the process run for too long (eg. piping it to 'less'). </p>
</div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.14
</small></address>
</body>
</html>
